import ValuePair from "./ValuePair";
import {loseloseHashCode, defaultToString} from "./loseloseHashCode";
import isEmpty from "../utils/isEmpty";

interface HashDictionaryLineInterface<TK, TV> {
  toStrFn: (item: any) => string;
  loseloseHashCode: loseloseHashCode;
  item: { [index: number]: ValuePair<TK, TV> };
  put: (key: TK, value: TV) => void;
  get: (key: TK) => ValuePair<TK, TV> | undefined;
  remove: (key: TK) => ValuePair<TK, TV> | undefined;
}

/**
 * 线性探查
 */
export default class HashDictionaryLine<TK, TV> implements HashDictionaryLineInterface<TK, TV> {
  item: { [p: number]: ValuePair<TK, TV> };
  loseloseHashCode: loseloseHashCode;
  toStrFn: (item: any) => string;

  constructor(toStrFn: (item: any) => string = defaultToString, max: number = 36) {
    this.toStrFn = toStrFn;
    this.item = {};
    this.loseloseHashCode = new loseloseHashCode(toStrFn, max)
  }

  get(key: TK): ValuePair<TK, TV> | undefined {
    let index = this.loseloseHashCode.getCode(key);
    if (this.item[index] == null) {
      return undefined;
    }
    while (this.item[index]) {
      if (this.item[index].key === key) {
        return this.item[index];
      }
      index++
    }
    return this.item[index]
  }

  put(key: TK, value: TV): void {
    let index = this.loseloseHashCode.getCode(key);
    if (this.item[index]) {
      while (this.item[index]) {
        if (this.item[index].key === key) {
          this.item[index].value = value
          return
        }
        index++
      }
    }
    this.item[index] = new ValuePair<TK, TV>(key, value);
  }

  remove(key: TK): ValuePair<TK, TV> | undefined {
    let index = this.loseloseHashCode.getCode(key);
    let rmItem:ValuePair<TK, TV> | undefined = undefined
    while (this.item[index]) {
      if (this.item[index].key === key) {
        rmItem = this.item[index];
        delete this.item[index];
        this.verifyRemoveSideEffect(key, index);
        break
      }
      index++
    }

    return rmItem;
  }


  verifyRemoveSideEffect(key: TK, removePosition: number) {
    // 被删除掉的元素的hash值
    const hash = this.loseloseHashCode.getCode(key);
    let index = removePosition + 1;
    while (this.item[index]) {
      const posHash = this.loseloseHashCode.getCode(this.item[index].key);
      // 首先判断是否是否比被删除掉的元素的hash值小, 如果是则前移;
      // 判断是否比当前移除的index小, 如果是则前移
      if (posHash <= hash || posHash <= removePosition) {
        this.item[removePosition] = this.item[index];
        delete this.item[index];
        removePosition = index;
      }
      index++
    }
  }
}

let map = new HashDictionaryLine<string,number>()
function print() {
  console.log("#-_-`-_-`-_-`-_-`-_-`-_-`-_-`-_-`-_-`-_-`-_#")
  console.log(map.get("Jack"));
  console.log(map.get("lidppp"));
}
print()
map.put("Jack",1);
print()
map.put("lidppp",2);
print()
map.put("Jack",3);
print()
map.remove("Jack");
print()
